class RegistrationForm extends Backbone.View
    emailIsValid: false
    passwordIsValid: false

    initialize: () ->
        @el = jQuery(@el)
        @emailBox = @el.find("input[name='email']")
        @passwordBox = @el.find("input[name='password']")
        @confirmationBox = @el.find("input[name='cpassword']")
        this.delegate()
        this.render()

    delegate: () ->
        context = this

        registerFunction = (e) ->
            e.preventDefault()
            context.registerUser()

        @emailBox.keyup(@validate)
        @passwordBox.keyup(@validate)
        @confirmationBox.keyup(@validate)
        @el.submit(registerFunction)

    render: () ->
        wrongColor = "rgb(255, 172, 98)"
        rightColor = "rgb(85, 255, 174)"

        if @emailBox.hasValue()
            if @emailIsValid
                @emailBox.highlight(rightColor)
            else
                @emailBox.highlight(wrongColor)

        if @passwordBox.hasValue()
            if @passwordIsValid
                @passwordBox.highlight(rightColor)
                @confirmationBox.highlight(rightColor)
            else
                @passwordBox.highlight(wrongColor)
                @confirmationBox.highlight(wrongColor)

    email: () ->
        @emailBox.val()

    password: () ->
        @passwordBox.val()

    cpassword: () ->
        @confirmationBox.val()

    validate: () =>
        @emailIsValid = checkEmail(this.email())
        @passwordIsValid = checkPassword(this.password(), this.cpassword())

        this.render()

        @emailIsValid and @passwordIsValid

    registerUser: () ->
        if !this.validate()
            alert("Email and/or password are not valid!")
            return

        email = this.email()
        password = this.password()

        success = () ->
            alert("You have been registered. Check your inbox email to activate your account.")

        error = newErrorCallback("Registration failed because of an error.", () => @el.fadeIn())

        user = new window.model.User()
        user.register(email, password, success, error)
        @el.fadeOut()


class LoginForm extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @emailBox = @el.find("input[name='email']")
        @passwordBox = @el.find("input[name='password']")
        this.delegate()
        this.render()

    delegate: () ->
        context = this

        loginFunction = (e) ->
            e.preventDefault()
            context.loginUser()

        @el.submit(loginFunction)

    email: () ->
        @emailBox.val()

    password: () ->
        @passwordBox.val()

    validate: () ->
        @emailBox.hasValue() and @passwordBox.hasValue()

    loginUser: () ->
        if not this.validate()
            alert("You need email and password to login!")
            return

        @el.fadeOut()

        success = (sessionHash) =>
            this.showLoggedGui()
            $.cookie(window.COOKIE_NAME, sessionHash)
            window.loadPersonalInfo()
            window.showPanel(window.profilePanel)
            window.profile.showSection("information")

        error = window.newErrorCallback("Cannot login!", () => @el.fadeIn())

        email = this.email()
        password = this.password()

        utils.User.login(email, password, success, error)

    showLoggedGui: () ->
        $(".notLoggedIn").fadeReplace($(".loggedIn"))

    hideLoggedGui: () ->
        $(".loggedIn").fadeReplace($(".notLoggedIn, .notLoggedIn *"))
        window.panels.visibles().fadeReplace(window.homePanel)


class Profile extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @model = window.targetUser

        @usernameArea = @el.find("#userHeader header")
        @descriptionArea = @el.find("#userHeader cite")
        @informationArea = @el.find("#information")
        @emailArea = @el.find("#userHeader .email")
        @avatarImage = @el.find("#userHeader .avatar")

        @skillSection = new ProfileSkillSection({ el: @el.find("#skills") })
        @feedbackSection = new ProfileFeedbackSection({ el: @el.find("#feedbacks")})

        @infoLink = @el.find("#infoLink")
        @skillLink = @el.find("#skillLink")
        @feedbackLink = @el.find("#feedbackLink")
        @sendMessageLink = @el.find("#sendMessageLink")

        @sendMessageForm = new MessageFormView({ el: @el.find("#sendMessage form") })

        @editButton = @el.find("#editProfile")
        @saveButton = @el.find("#saveProfile")
        @promoteButton = @el.find("#promote")
        @demoteButton = @el.find("#demote")
        @friendsButton = @el.find("#showFriends")
        @addFriendButton = @el.find("#addFriend")
        @removeFriendButton = @el.find("#removeFriend")
        @killButton = @el.find("#kill")
        @forcePasswordButton = @el.find("#forcePassword")

        @fileArea = @el.find("input[type='file']")
        @uploadButton = @el.find("#uploadAvatar")
        @deleteAvatarButton = @el.find("#deleteAvatar")
        @uploadForm = @el.find("#uploadForm")

        this.delegate()
        this.render()

    delegate: () ->
        currentUser.on("change:id", @idChanged)
        @model.on("change:id", @idChanged)
        @model.on("change:name", @nameChanged)
        @model.on("change:description", @descriptionChanged)
        @model.on("change:information", @informationChanged)
        @model.on("change:email", @emailChanged)

        @editButton.click(@enableEditMode)
        @saveButton.click(@saveProfile)
        @uploadButton.click(@uploadAvatar)
        @deleteAvatarButton.click(@deleteAvatar)
        @killButton.click(@deleteUser)
        @forcePasswordButton.click(@forcePasswordChange)
        @demoteButton.click(@demoteUser)
        @promoteButton.click(@promoteUser)
        @removeFriendButton.click(@removeFriend)
        @addFriendButton.click(@addFriend)

    updateLinks: () ->
        prefix = "#/users/" + @model.get("id")
        @infoLink.attr("href", prefix + "/information")
        @skillLink.attr("href", prefix + "/skills")
        @feedbackLink.attr("href", prefix + "/feedbacks")
        @friendsButton.attr("href", prefix + "/friends")
        @sendMessageLink.attr("href", prefix + "/sendMessage")

    idChanged: () =>
        if currentUser.isVisitor()
            @promoteButton.hide()
            @demoteButton.hide()
            @editButton.hide()
            @addFriendButton.hide()
            @removeFriendButton.hide()
            @forcePasswordButton.hide()
            @sendMessageLink.hide()
        else
            @sendMessageLink.show()

            if currentUser.isAdmin()
                if targetUser.isAdmin()
                    @promoteButton.hide()
                else
                    @promoteButton.show()
            else
                @promoteButton.hide()

            if currentUser.isSuperUser()
                @editButton.show()
                @killButton.show()
                @deleteAvatarButton.show()
                @forcePasswordButton.show()
                if targetUser.isAdmin()
                    @demoteButton.show()
                else
                    @demoteButton.hide()
            else
                @killButton.hide()
                @deleteAvatarButton.hide()
                @forcePasswordButton.hide()

            if isSelfProfile()
                @editButton.show()
                @promoteButton.hide()
                @demoteButton.hide()
                @addFriendButton.hide()
                @removeFriendButton.hide()
                @killButton.hide()
                @forcePasswordButton.show()
            else
                if !currentUser.isSuperUser()
                    @editButton.hide()
                this.analyzeFriends()

        this.updateLinks()
        @skillSection.refresh()
        @sendMessageForm.recipient = targetUser
        @avatarImage.attr("src", "#{@model.url()}/avatar")

    analyzeFriends: () ->
        success = () =>
            if isSelfProfile()
                @addFriendButton.hide()
                @removeFriendButton.hide()
                return
            if targetUser.friends.where({id: currentUser.get("id")}).length == 0
                @addFriendButton.show()
                @removeFriendButton.hide()
            else
                @addFriendButton.show()
                @removeFriendButton.hide()

        targetUser.friends.fetch
            success: success

    nameChanged: () =>
        @usernameArea.find(".normal").html(@model.get("name"))

    descriptionChanged: () =>
        @descriptionArea.find(".normal").html(@model.get("description"))

    informationChanged: () =>
        @informationArea.find(".normal").html(@model.get("information"))

    emailChanged: () =>
        @emailArea.find(".normal").html(@model.get("email"))

    showSection: (name) ->
        @el.find("#content section").hide()
        @el.find("#" + name).show()

    enableEditMode: () =>
        @editButton.fadeReplace(@saveButton)
        @usernameArea.find(".edit input").val(@usernameArea.find(".normal").text())
        @descriptionArea.find(".edit input").val(@descriptionArea.find(".normal").text())
        @informationArea.find(".edit textarea").val(@informationArea.find(".normal").text())
        @emailArea.find(".edit input").val(@emailArea.find(".normal").text())
        @el.find(".normal").fadeReplace(@el.find(".edit"))
        this.showSection("information")

    validate: () ->
        @usernameArea.find(".edit input").hasValue()    and
        @descriptionArea.find(".edit input").hasValue() and
        @informationArea.find(".edit textarea").hasValue() and
        @emailArea.find(".edit input").hasValue()

    saveProfile: () =>
        if !this.validate()
            alert("Fill the fields with appropriate values!")
            return

        newUsername = @usernameArea.find(".edit input").val()
        newDescription = @descriptionArea.find(".edit input").val()
        newInformation = @informationArea.find(".edit textarea").val()
        newEmail = @emailArea.find(".edit input").val()

        attributes =
            name: newUsername
            description: newDescription
            information: newInformation
            email: newEmail

        success = () =>
            if isSelfProfile()
                @model.copyFrom(currentUser)
            @editButton.fadeIn()

        error = newErrorCallback("There was an error editing the profile!", () => @editButton.fadeIn())

        options =
            success: success
            error: error

        if currentUser.isSuperUser()
            targetUser.save(attributes, options)
        else
            currentUser.save(attributes, options)

        @saveButton.fadeOut()
        @el.find(".edit").fadeReplace(@el.find(".normal"))

    uploadAvatar: () =>
        if @fileArea.isEmpty()
            alert("Select a file before proceeding!")
            return

        @uploadButton.attr("disabled", "disabled")

        data = new FormData(@uploadForm[0])
        context = this

        success = () =>
            avatar = $("#userHeader .avatar")
            avatar.attr("src", avatar.attr("src"))
            context.uploadButton.attr("value", "Upload")
            context.uploadButton.removeAttr("disabled")

        error = newErrorCallback("An error occurred while uploading!", () =>
            @uploadButton.removeAttr("disabled")
            @uploadButton.attr("value", "Upload")
        )

        progress = (e) ->
            percent = Number(100 * e.loaded / e.total).toFixed(2)
            context.uploadButton.attr("value", "#{percent}%")
            if (percent == 100.00)
                success()

        currentUser.uploadAvatar(data, success, error, progress)

    deleteAvatar: () =>
        success = () ->
            avatar = $("#userHeader .avatar")
            avatar.attr("src", avatar.attr("src"))

        error = newErrorCallback("Cannot delete this avatar!")

        targetUser.deleteAvatar(success, error)

    deleteUser: () =>
        if (currentUser.isSuperUser())
            if !confirm("Are you sure you want to permantely erase all data about this user? This action cannot be undone.")
                return

            success = () ->
                showPanel(homePanel)
                alert("The user has been terminated.")

            error = newErrorCallback("Cannot delete this user!")

            targetUser.destroy
                success: success
                error: error
        else
            alert("You are not allowed to delete users.")

    forcePasswordChange: () =>
        if currentUser.isSuperUser() or isSelfProfile()
            pass = prompt("Insert new password:")
            cpass = prompt("Confirm password:")

            if pass != cpass
              alert("The two passwords don't match!")
              return

            success = () -> alert("User password changed successfully!")
            error = newErrorCallback("Cannot change user password!")

            if isSelfProfile()
                currentUser.forcePassword(pass, success, error)
            else
                targetUser.forcePassword(pass, success, error)
        else
            alert("You are not allowed to perform this action!")

    demoteUser: () =>
        if (currentUser.isSuperUser())
            success = () ->
                profile.demoteButton.hide();
                alert("This administrator has been demoted!")
            error = newErrorCallback("Cannot demote this user!")

            targetUser.demote(success, error)
        else
            alert("You are not allowed to demote.")

    promoteUser: () =>
        if (currentUser.isAdmin())
            success = () ->
                @promoteButton.hide()
                @demoteButton.show()
                alert("The user has been promoted!")
            error = newErrorCallback("Cannot promote this user!")

            targetUser.promote(success, error)
        else
          alert("You are not allowed to promote.")

    removeFriend: () =>
        success = () =>
            alert(targetUser.get("name") + " is no longer your friend!")
            @removeFriendButton.hide()
            @addFriendButton.show()

        error = newErrorCallback("Cannot cancel friendship!")

        currentUser.removeFriend(targetUser, success, error)

    addFriend: () =>
        success = () -> alert("You have sent a friendship request!")
        error = newErrorCallback("Cannot request friendship to that user!")

        request = new model.FriendshipRequest()
        request.set("target", targetUser)
        request.send(success, error)

class SkillCollectionView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @comboMode = @el.is("select")
        @compactMode = @el.hasClass("compact")

        if !@model
            @model = new collection.Skill()

        this.render()
        this.delegate()

    delegate: () ->
        @model.on("add", @skillAdded)
        @model.on("reset", @skillReset)
        @model.on("remove", @skillRemoved)

    createSkillItem: (skill) ->
        name = skill.get("name")
        description = skill.get("description")
        id = skill.get("id")

        code = "
            <li class='skill' id='s#{id}'>
                <h3 class='name'>#{name}</h3>
                <span class='description'>#{description}</span>
            </li>"

        return $(code)

    createCompactSkillItem: (skill) ->
        name = skill.get("name")
        id = skill.get("id")

        return $("<li id='s#{id}'><input type='checkbox' /> #{name}</li>")

    createSkillOption: (skill) ->
        name = skill.get("name")
        id = skill.get("id")

        return $("<option value='#{id}'>#{name}</option>")

    skillAdded: (skill) =>
        if @comboMode
            item = this.createSkillOption(skill)
        else
            if @compactMode
                item = this.createCompactSkillItem(skill)
            else
                item = this.createSkillItem(skill)

        if @onItemCreated
            this.onItemCreated(item, skill)

        @el.append(item)

    skillReset: () =>
        @el.empty()
        if @model and @model.length > 0
            for i in [0..(@model.length - 1)]
                this.skillAdded(@model.at(i))

    render: () ->
        this.skillReset()

    skillRemoved: (skill) =>
        this.skillReset()


class ProfileSkillSection extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)

        list = @el.find("ul")

        @skillList = new SkillCollectionView({ el: list, model: targetUser.skills })

        if skillDatabase.isEmpty()
            skillDatabase.fetch
                success: @populateCombo
        else
            this.populateCombo()

        @addForm = @el.find("#addSkill")
        @addButton = @el.find("#addSkill #addSkillButton")
        @deleteButton = @el.find("#addSkill #delSkillButton")
        @proposeButton = @el.find("#proposeSkill input[type='button']")

        @proposeForm = @el.find("#proposeSkill")
        @proposalNameBox = @el.find("#proposeSkill input[name='proposal']")
        @proposalDescriptionBox = @el.find("#proposeSkill input[name='proposalDescription']")

        this.delegate()

    delegate: () ->
        @addButton.click(@addSkill)
        @deleteButton.click(@deleteSkill)
        @proposeButton.click(@proposeSkill)
        @skillList.onItemCreated = @hookListItem

    hookListItem: (item, skill) =>
        if !isSelfProfile()
            return

        sid = skill.get("id")
        removeLink = $("<span> (<a href='remove#{sid}'>X</a>) </span>")
        title = item.find("h3")
        title.append(removeLink)

        context = this
        removeLink.find("a").click (e) ->
            e.preventDefault()
            context.removeSkill(sid)

    populateCombo: () =>
        combo = @el.find("select")
        @skillCombo = new SkillCollectionView({ el: combo, model: skillDatabase })

    refresh: () ->
        if currentUser.isVisitor()
            @addForm.hide()
            @proposeForm.hide()
            @deleteButton.hide()
        else
            @proposeForm.show()

            if isSelfProfile()
                @addForm.show()
            else
                @addForm.hide()

            if currentUser.isAdmin()
                @proposeForm.find("h3").html("Declare a skill!")
            else
                @proposeForm.find("h3").html("Propose a skill!")

            if currentUser.isSuperUser()
                @deleteButton.show()
            else
                @deleteButton.hide()

        @skillList.model.url = () -> targetUser.url() + "/skills"
        @skillList.model.reset()
        @skillList.model.fetch()

    addSkill: () =>
        if skillDatabase.isEmpty()
            skillDatabase.fetch
                success: @addSkill
            return

        sid = Number(@skillCombo.el.val())
        skill = skillDatabase.getById(sid)

        if !skill
            alert("No such skill!")
            return

        success = () =>
            @skillList.model.add(skill)

        error = newErrorCallback("Cannot add that skill!")

        currentUser.addSkill(skill, success, error)

    deleteSkill: () =>
        sid = Number(@skillCombo.el.val())
        skill = skillDatabase.getById(sid)

        if !skill
            alert("That skill does not exist!")
            return

        success = () =>
            @skillList.model.remove(skill)
            @skillList.render()

        error = newErrorCallback("Cannot delete that skill!")

        thatSkill = new model.Skill()
        thatSkill.set("id", sid)
        thatSkill.url = () -> "#{ROOT_URL}/skills"
        thatSkill.destroy
            success: success
            error: error

    proposeSkill: () =>
        if @proposalNameBox.isEmpty() or @proposalDescriptionBox.isEmpty()
            alert("Fill the fields correctly!")
            return

        skill = new model.Skill()
        skill.set("name", @proposalNameBox.val())
        skill.set("description", @proposalDescriptionBox.val())

        if currentUser.isAdmin()
            success = () -> alert("Skill created! Reload the page to see it in the list.")
        else
            success = () -> alert("Your proposal has been posted and will be reviewed asap!")

        error = newErrorCallback("Cannot send proposal!")

        skill.propose(success, error)

    removeSkill: (id) =>
        skill = skillDatabase.getById(id)

        if !skill
            alert("No such skill to remove!")
            return

        success = () => @skillList.model.remove(skill)
        error = newErrorCallback("Cannot remove that skill!")

        thatSkill = new model.Skill()
        thatSkill.set("id", id)
        thatSkill.url = () -> currentUser.url() + "/skills/#{id}"
        thatSkill.destroy
            success: success
            error: error


class FeedbackCollectionView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)

        if !@model
            @model = new collection.Feedback()

        this.delegate()

    delegate: () ->
        @model.on("add", @feedbackAdded)
        @model.on("reset", @feedbackReset)

    feedbackAdded: (feedback) =>
        rating = feedback.get("rating")
        author = feedback.get("author").name
        id     = feedback.get("author").id
        text   = feedback.get("text")

        if feedback.get("author").get
            author = feedback.get("author").get("name")
        if feedback.get("author").get
            id = feedback.get("author").get("id")

        if rating.toString().length > 1
            if rating.indexOf("One") == 0
                rating = 1
            else if rating.indexOf("Two") == 0
                rating = 2
            else if rating.indexOf("Three") == 0
                rating = 3
            else if rating.indexOf("Four") == 0
                rating = 4
            else
                rating = 5

        code = "
            <li class='feedback'>
                <img class='avatar' src='#{ROOT_URL}/users/#{id}/avatar'/>
                <h3 class='title'>#{author} said: #{rating} stars</h3>
                <p class='comment'>#{text}</p>
            </li>"

        item = $(code)
        @el.append(item)

    feedbackReset: () =>
        @el.empty()

        if @model.length > 0
            for i in [0..(@model.length - 1)]
                this.feedbackAdded(@model.at(i))


class ProfileFeedbackSection extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @form = @el.find("#sendFeedbackForm")
        @ratingCombo = @form.find("select[name='rating']")
        @commentArea = @form.find("textarea[name='comment']")

        list = @el.find("ul")
        combo = @el.find("select")

        @skillCombo = new SkillCollectionView({ el: combo, model: targetUser.skills })
        @feedbackList = new FeedbackCollectionView({ el: list })

        @showButton = @el.find("#selectSkill input")

        this.delegate()

    delegate: () ->
        @showButton.click(@showFeedbacks)

        callback = @sendFeedback
        @form.submit (e) ->
            e.preventDefault()
            callback()

    showFeedbacks: () =>
        sid = @skillCombo.el.val()
        @feedbackList.model.url = () -> targetUser.url() + "/skills/#{sid}/feedbacks"
        @feedbackList.model.fetch()

    refresh: () ->
        if currentUser.isVisitor()
            @form.hide()
        else
            @form.show()

        @skillCombo.model.reset()
        @skillCombo.model.fetch()

    sendFeedback: () =>
        if @ratingCombo.isEmpty() or @commentArea.isEmpty()
            alert("Fill the required fields!")
            return

        sid = @skillCombo.el.val()
        rating = @ratingCombo.val()
        comment = @commentArea.val()
        author = currentUser

        feedback = new model.Feedback()
        feedback.url = () -> targetUser.url() + "/skills/#{sid}/feedbacks"

        attributes =
            rating: rating
            text: comment

        success = () =>
            feedback.set("author", author)
            @feedbackList.model.add(feedback)

        error = newErrorCallback("Cannot send feedback!")

        options =
            success: success
            error: error

        feedback.save(attributes, options)


class MessageFormView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @textArea = @el.find("textarea")
        this.delegate()

    delegate: () ->
        context = this
        callback = (e) ->
            e.preventDefault()
            context.sendMessage()

        @el.submit(callback)

    sendMessage: () ->
        if @textArea.isEmpty()
            alert("Insert a message before sending!")
            return

        if !@recipient and !@recipientId
            return

        if @onMessageSent
            externalCallback = @onMessageSent
            success = () =>
                externalCallback()
                alert("Message sent!")
        else
            success = () -> alert("Message sent!")

        error = newErrorCallback("Cannot send message!")

        message = new model.Message()
        message.set("text", @textArea.val())

        if @recipient
            message.sendTo(@recipient, success, error)
        else
            message.sendToId(@recipientId, success, error)


class MessageCollectionView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        this.delegate()

    delegate: () ->
        @model.on("add", @messageAdded)
        @model.on("reset", @messageReset)

    createMessageItem: (message) =>
        sender = message.get("sender").name
        id     = message.get("sender").id
        text   = message.get("text")
        date   = new Date(Number(message.get("date")))

        if message.get("sender").get
            sender = message.get("sender").get("name")
            id = message.get("sender").get("id")

        code = "
            <li class='message'>
                <img class='avatar' src='#{ROOT_URL}/users/#{id}/avatar' />
                <h3 class='sender'>#{sender} <a href='#/replyto/#{id}'> <img src='icons/reply.png' class='reply' /> </a> </h3>
                <p class='text'>#{text}</p>
                <p class='date'>sent on #{formatDate(date,true)}</p>
            </li>"

        return $(code)

    createFormView: (recipientId) ->
        code = "
            <form name='replyForm' id='replyForm'>
                <textarea rows='6' cols='100' name='text'>Message</textarea>
                <input type='submit' value='Send' class='right' />
            </form>"
        form = $(code)

        view = new MessageFormView({ el : form })
        view.recipientId = recipientId
        view.onMessageSent = () => form.remove()

        return view

    messageAdded: (message) =>
        context = this

        item = this.createMessageItem(message)
        replyLink = item.find("a")

        sender = message.get("sender")

        if sender.get
            id = sender.get("id")
        else
            id = sender.id

        replyLink.click (e) =>
            if item.find("form").size() == 0
                formView = context.createFormView(id)
                item.append(formView.el)

        @el.append(item)

    messageReset: () =>
        @el.empty()
        if @model.length > 0
            for i in [0..(@model.length - 1)]
                this.messageAdded(@model.at(i))


class FriendshipRequestCollectionView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        this.delegate()

    delegate: () ->
        @model.on("add", @requestAdded)
        @model.on("reset", @requestReset)

    createRequestItem: (request) =>
        sender = request.getSenderName()
        id     = request.getId()
        date   = new Date(Number(request.get("date")))

        code = "
            <li class='request'>
                <img class='avatar' src='#{ROOT_URL}/users/#{id}/avatar' />
                <h3 class='sender'>#{sender}</h3> <span class='date'>#{formatDate(date)}</span> <br/>
                <a href='#/accept/#{id}'>Accept</a> &nbsp; - &nbsp; <a href='#/decline/#{id}'>Decline</a>
            </li>"
        return $(code)

    requestAdded: (request) =>
        item = this.createRequestItem(request)

        id = request.getId()
        sender = request.getSenderName()

        acceptLink  = item.find("a[href='#/accept/#{id}']")
        declineLink = item.find("a[href='#/decline/#{id}']")

        error = newErrorCallback("Cannot process that request!")

        successAccepted = () =>
            @model.remove(request)
            item.html("<em><strong>#{sender}</strong> has been accepted</em>")

        successDeclined = () =>
            @model.remove(request)
            item.html("<em><strong>#{sender}</strong> has been rejected</em>")

        acceptLink.click (e) =>
            e.preventDefault()
            request.accept(successAccepted, error)

        declineLink.click (e) =>
            e.preventDefault()
            request.decline(successDeclined, error)

        @el.append(item)

    requestReset: () =>
        @el.empty()
        if @model.length > 0
            for i in [0..(@model.length - 1)]
                this.requestAdded(@model.at(i))


class SearchView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @searchBox = @el.find("#skillQuickSearchBox")
        @friendBox = @el.find("#searchForm input[name='onlyFriends'], #searchForm label")
        @form = @el.find("#searchForm")
        @barSearch = $("#quickSearch form")

        @nameSearchBox = @el.find("#searchByName input[type='text']")
        @nameSearchButton = @el.find("#searchByName input[type='button']")

        @backButton = $("#backToSearch")

        this.ensureSkillsAreThere()
        this.delegate()

    delegate: () ->
        @searchBox.keyup(@quickSearch)
        @form.submit(@search)
        @barSearch.submit(@redirectSearch)

        @nameSearchButton.click(@searchByName)
        @backButton.click () => window.showPanel(searchPanel)

    ensureSkillsAreThere: () ->
        if skillDatabase.isEmpty()
            skillDatabase.fetch
                success: @populateList
        else
            this.populateList()

    populateList: () =>
        @skillList = new SkillCollectionView({ el: @el.find("#skillList ul"), model: skillDatabase })
        this.ready()

    show: () ->
        if window.isLogged()
            @friendBox.show()
        else
            @friendBox.hide()

        this.ensureSkillsAreThere()

    ready: () =>
        @skillItems = @skillList.el.find("li")

        if @searchBox.hasValue()
            this.quickSearch()

    redirectSearch: (e) =>
        e.preventDefault()
        @searchBox.val(@barSearch.find("input").val())
        window.showPanel(searchPanel)
        this.show()

    quickSearch: () =>
        query = @searchBox.val().toLowerCase()

        callback = () ->
            item = $(this)
            itemText = item.text().toLowerCase();
            if itemText.indexOf(query) < 0
                item.hide()
            else
                item.show()

        @skillItems.each(callback)

    search: (e) =>
        e.preventDefault()

        rating = @form.find("select").val()

        if @form.find("input[name='onlyFriends']").attr("checked")
            onlyFriends = true
        else
            onlyFriends = false

        skills = ""

        @skillItems.each () ->
            if $(this).find("input").attr("checked")
                skills += "skills=" + $(this).attr("id").substr(1) + "&"

        skills = skills.substr(0, skills.length - 1)

        if rating > 0
            query = "minRating=" + rating + "&"
        else
            query = ""

        if onlyFriends
            query += "onlyFriends=1&"
        else
            query += "onlyFriends=0&"

        query += skills

        window.userView.model.url = () -> window.ROOT_URL + "/help?" + query
        window.userView.model.reset()
        window.userView.model.fetch()
        window.showPanel(resultPanel)

    searchByName: (e) =>
        e.preventDefault()

        if @nameSearchBox.isEmpty()
            alert("Fill in the search box!")
            return;

        name = @nameSearchBox.val()

        window.userView.model.url = () -> window.ROOT_URL + "/users?name=#{name}"
        window.userView.model.reset()
        window.userView.model.fetch()
        window.showPanel(resultPanel)


class UserCollectionView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @model = new window.collection.User()
        this.delegate()

    delegate: () ->
        @model.on("add", @userAdded)
        @model.on("reset", @userReset)

    createUserItem: (user) ->
        name = user.get("name")
        id   = user.get("id")
        description = user.get("description")
        email = user.get("email")

        code = "
            <li class='user'>
                <img src='#{ROOT_URL}/users/#{id}/avatar' class='avatar' />
                <a href='#/users/#{id}'> <h3 class='name'> #{name} </h3> </a>
                <em class='description'>#{description}</em> <br/>
                <em class='email'>#{email}</em>
            </li>"

        return $(code)

    userAdded: (user) =>
        item = this.createUserItem(user)
        @el.append(item)

    userReset: =>
        @el.empty()
        if @model.length > 0
            for i in [0..(@model.length - 1)]
                this.userAdded(@model.at(i))


class ProposalsView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)
        @skillList = new SkillCollectionView({ el: @el.find("ul") })
        @skillList.model.url = () -> "#{ROOT_URL}/skills/proposals"
        this.delegate()

    delegate: () ->
        @skillList.onItemCreated = @hookListItem

    hookListItem: (item, skill) =>
        sid = skill.get("id")
        title = item.find("h3")
        approveLink = $("<a href='#/approve/#{sid}' title='Approve'> <img class='small' src='icons/add.png' /> </a>")
        declineLink = $("<a href='#/decline/#{sid}' title='Reject'> <img class='small' src='icons/delete.png' /> </a> ")

        title.append(approveLink)
        title.append(declineLink)

        context = this

        approveLink.click (e) ->
            e.preventDefault()
            context.approve(skill)

        declineLink.click (e) ->
            e.preventDefault()
            context.decline(skill)

    refresh: () ->
        @skillList.model.reset()
        @skillList.model.fetch()

    approve: (skill) =>
        success = () =>
            @skillList.model.remove(skill)
            alert("The skill has been approved!")

        error = newErrorCallback("Cannot approve this skill!")

        skill.approve(success, error)

    decline: (skill) =>
        success = () =>
            @skillList.model.remove(skill)
            alert("That skill has been declined!")

        error = newErrorCallback("Cannot recjet this skill!")

        skill.decline(success, error)


class AccountView extends Backbone.View
    initialize: () ->
        @el = jQuery(@el)

        @emailForm = @el.find("#resetViaEmailForm")
        @emailBox = @emailForm.find("input[type='email']")

        @usernameForm = @el.find("#resetViaUsernameForm")
        @usernameBox = @usernameForm.find("input[type='text']")

        @manualActivation = @el.find("#manualActivation")

        @inactiveUsers = new collection.User()
        @inactiveUsers.url = () -> "#{ROOT_URL}/accounts/inactive"

        @accountList = @manualActivation.find("ul")

        this.delegate()

    delegate: () ->
        @emailForm.submit(@resetPasswordViaEmail)
        @usernameForm.submit(@resetPasswordViaUsername)
        @inactiveUsers.on("reset", @accountReset)
        currentUser.on("change:id", @idChanged)

    idChanged: () =>
        if currentUser.isSuperUser()
            @manualActivation.show()
        else
            @manualActivation.hide()

    resetPasswordViaEmail: (e) =>
        e.preventDefault()

        if @emailBox.isEmpty()
            alert("Enter an email address!")
            return

        success = () ->
            alert("Password has been reset. Check your inbox for new messages.")

        error = newErrorCallback("Cannot reset password!", () => @emailForm.fadeIn())

        @emailForm.fadeOut()
        utils.User.resetViaEmail(@emailBox.val(), success, error)

    resetPasswordViaUsername: (e) =>
        e.preventDefault()

        if @usernameBox.isEmpty()
            alert("Enter an username!")
            return

        success = () ->
            alert("Password has been reset. Check your inbox for new messages.")

        error = newErrorCallback("Cannot reset password!", () => @usernameForm.fadeIn())

        @usernameForm.fadeOut()
        utils.User.resetViaUsername(@usernameBox.val(), success, error)

    refreshAccountList: () ->
        @accountList.empty()
        @inactiveUsers.fetch()

    accountAdded: (account) ->
        email = account.get("email")
        id    = account.get("id")

        item = $("<li>#{email} : <a href='#/accounts/#{id}'>Activate</a></li>")

        item.find("a").click () =>
            success = () =>
                alert("User #{email} activated!")
                item.remove()

            error = newErrorCallback("Cannot activated that user!")

            utils.User.activate(id, success, error)


        @accountList.append(item)

    accountReset: () =>
        if @inactiveUsers.length == 0
            @accountList.append($("<li>No account to display</li>"))
            return

        for i in [0..(@inactiveUsers.length - 1)]
            this.accountAdded(@inactiveUsers.at(i))


class MainRouter extends Backbone.Router
    routes:
        "users/:id": "showUserInfo"
        "users/:id/information": "showUserInfo"
        "users/:id/skills": "listUserSkills"
        "users/:id/feedbacks": "listUserFeedbacks"
        "self": "showMyProfile"
        "self/skills": "listMySkills"
        "self/feedbacks": "listMyFeedbacks"
        "self/messages": "listMyMessages"
        "self/requests": "listMyRequests"
        "help": "search"
        "users": "listAllUsers"
        "users/:id/sendMessage": "sendMessageToUser"
        "users/:id/friends": "showFriends"
        "self/friends": "showMyFriends"
        "skills/proposals" : "showProposals"
        "accountHelp" : "account"
        "home" : "goHome"


# Loading of views
$ () ->
    window.homePanel = $("#homePanel")
    window.profilePanel = $("#profilePanel")
    window.searchPanel = $("#searchPanel")
    window.messagePanel = $("#messagePanel")
    window.requestPanel = $("#requestPanel")
    window.resultPanel = $("#resultPanel")
    window.proposalsPanel = $("#proposalsPanel")
    window.accountPanel = $("#accountPanel")
    #window.panels = $("#homePanel, #profilePanel, #searchPanel, #messagePanel, #requestPanel, #resultPanel, #proposalsPanel, #accountPanel")
    window.panels = $(".body > div")

    window.showPanel = (panel) ->
        if panel.is(":visible")
            return
        window.panels.visibles().fadeReplace(panel)

    window.skillDatabase = new model.SkillDatabase()
    window.skillDatabase.fetch()

    window.registrationView = new RegistrationForm({ el : $("#registrationForm")})
    window.loginView = new LoginForm({ el : $("#loginForm") })

    window.personalMessageView = new MessageCollectionView({ el: $("#messagePanel ul"), model: window.currentUser.messages })

    window.profile = new Profile({ el : $("#profilePanel") })
    window.searchView = new SearchView({ el: $("#searchPanel") })

    window.requestView = new FriendshipRequestCollectionView({ el: $("#requestPanel ul"), model: window.currentUser.requests })
    window.userView = new UserCollectionView({ el: $("#resultPanel ul") })

    window.proposalsView = new ProposalsView({ el: proposalsPanel })

    window.accountView = new AccountView({ el : accountPanel })

    mainRouter = new MainRouter()

    mainRouter.on "route:listUserSkills", (id) =>
        window.showPanel(profilePanel)
        profile.showSection("skills")

        if targetUser.get("id") != id
            profile.model.set("id", id)
            profile.model.fetch
                success: () -> profile.skillSection.refresh()
        else
            profile.skillSection.refresh()


    mainRouter.on "route:showUserInfo", (id) =>
        window.showPanel(profilePanel)
        profile.showSection("information")

        if targetUser.get("id") != id
            profile.model.set("id", id)
            profile.model.fetch()

    mainRouter.on "route:listUserFeedbacks", (id) =>
        window.showPanel(profilePanel)
        profile.showSection("feedbacks")

        if targetUser.get("id") != id
            profile.model.set("id", id)
            profile.model.fetch
                success: () -> profile.feedbackSection.refresh()
        else
            profile.feedbackSection.refresh()

    mainRouter.on "route:listMyFeedbacks", () =>
        window.showPanel(profilePanel)
        profile.showSection("feedbacks")

        profile.model.copyFrom(window.currentUser)
        profile.model.fetch
            success: () =>
                profile.feedbackSection.refresh()

    mainRouter.on "route:sendMessageToUser", () =>
        window.showPanel(profilePanel)
        profile.showSection("sendMessage")

    mainRouter.on "route:listMyMessages", () =>
        window.showPanel(messagePanel)
        personalMessageView.model.reset()
        personalMessageView.model.fetch()

    mainRouter.on "route:listMyRequests", () =>
        window.showPanel(requestPanel)
        requestView.model.reset()
        requestView.model.fetch()

    mainRouter.on "route:search", () =>
        window.showPanel(searchPanel)
        searchView.searchBox.val("")
        searchView.show()

    mainRouter.on "route:listAllUsers", () =>
        window.showPanel(resultPanel)
        userView.model.url = () -> window.ROOT_URL + "/users"
        userView.model.reset()
        userView.model.fetch()

    mainRouter.on "route:showMyProfile", () =>
        window.showPanel(profilePanel)
        profile.showSection("information")
        window.loadPersonalInfo()

    $(".barContent a[href='#/logout']").click (e) =>
        e.preventDefault()
        $.cookie(window.COOKIE_NAME, null)
        loginView.hideLoggedGui()

    mainRouter.on "route:showFriends", (id) =>
        window.showPanel(resultPanel)
        userView.model.url = () -> "#{ROOT_URL}/users/#{id}/friends"
        userView.model.reset()
        userView.model.fetch()

    mainRouter.on "route:showMyFriends", () =>
        window.showPanel(resultPanel)
        userView.model.url = () -> "#{ROOT_URL}/users/" + currentUser.get("id") + "/friends"
        userView.model.reset()
        userView.model.fetch()

    mainRouter.on "route:showProposals", () =>
        window.showPanel(proposalsPanel)
        proposalsView.refresh()

    mainRouter.on "route:account", () =>
        window.showPanel(accountPanel)
        accountView.refreshAccountList()

    mainRouter.on "route:goHome", () =>
        window.showPanel(homePanel)

    # Interface fix
    $(window).resize () ->
        labels = $(".right .quickIcon label")
        if $(".body").width() < 866
            labels.hide()
        else
            labels.show()

    if isLogged()
        loginView.showLoggedGui()
        if !currentUser.get("id")
            window.loadPersonalInfo()

    Backbone.history.start()

